﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AbstraX.ClientInterfaces;
using System.Reflection;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;
using SolutionFramework.Entities;
using AbstraX.XPathBuilder;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using MvvmTreeView;
using AbstraX;
using AbstraX.Contracts;

namespace TreeBuilderTest.Entities
{
    public class BaseTypeElement : IElement
    {
        private Type baseType;
        private IBase parent;
        public event ChildrenLoadedHandler ChildrenLoaded;
        private string queryWhereProperty;
        private object queryWhereValue;

        public IAbstraXExtension LoadExtension(IBase baseObject, ITreeNode treeNode)
        {
            return null;
        }

        public BaseTypeElement(Type baseType, IBase parent)
        {
            this.baseType = baseType;
            this.parent = parent;
            this.FolderKeyPair = baseType.Namespace;
        }

        public BaseTypeElement(IType baseIType, IBase parent)
        {
            try
            {
                this.baseType = Type.GetType(baseIType.FullyQualifiedName, true);
                this.parent = parent;
            }
            catch (Exception ex)
            {
                Debugger.Break();
            }
        }

        public string ID
        {
            get
            {
                return this.MakeID("Type='" + this.DataType.FullyQualifiedName + "'");
            }
        }

        public string FolderKeyPair { get; set; }

        public bool IsContainer
        {
            get 
            {
                return false;
            }
        }

        public IType DataType
        {
            get 
            {
                var type = new BaseType(baseType);

                return type;
            }
        }

        public IEnumerable<IAttribute> Attributes
        {
            get 
            {
                if (queryWhereProperty != null && queryWhereProperty == "Property")
                {
                    var property = (PropertyInfo)baseType.GetProperties().Where(p => p.Name == (string) queryWhereValue).Single();

                    yield return new BasePropertyAttribute(property, this);
                }
                else
                {
                    foreach (PropertyInfo property in baseType.GetProperties())
                    {
                        if (property.PropertyType.IsPrimitive || AttributeType.Types.Contains(property.PropertyType))
                        {
                            yield return new BasePropertyAttribute(property, this);
                        }
                    }
                }
            }
        }

        public IEnumerable<IOperation> Operations
        {
            get 
            {
                foreach (MethodInfo method in baseType.GetMethods())
                {
                    if (!method.Name.StartsWith("get_") && !method.Name.StartsWith("set_") && !method.Name.StartsWith("add_") && !method.Name.StartsWith("remove_"))
                    {
                        yield return new BaseMethodOperation(method, this);
                    }
                }

                foreach (ConstructorInfo constructor in baseType.GetConstructors())
                {
                    yield return new BaseConstructorOperation(constructor, this);
                }
            }
        }

        public void LoadChildren()
        {
            throw new NotImplementedException();
        }

        public IEnumerable<IElement> ChildElements
        {
            get 
            {
                if (queryWhereProperty != null && queryWhereProperty == "Property")
                {
                    var property = (PropertyInfo)baseType.GetProperties().Where(p => p.Name == (string)queryWhereValue).Single();

                    yield return new BasePropertyElement(property, this);
                }
                else
                {
                    foreach (PropertyInfo property in baseType.GetProperties())
                    {
                        if (!property.PropertyType.IsPrimitive && !AttributeType.Types.Contains(property.PropertyType))
                        {
                            yield return new BasePropertyElement(property, this);
                        }
                    }
                }
            }
        }

        public string ParentID
        {
            get 
            {
                return this.Parent.ID;
            }
        }

        public string Name
        {
            get 
            {
                return this.baseType.Name;
            }
        }

        public string DesignComments
        {
            get { throw new NotImplementedException(); }
        }

        public string Documentation
        {
            get { throw new NotImplementedException(); }
        }

        public bool HasDocumentation
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public string DocumentationSummary
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public string ImageURL
        {
            get { throw new NotImplementedException(); }
        }

        public IBase Parent
        {
            get 
            {
                return parent;
            }
        }

        public System.ServiceModel.DomainServices.Client.DomainContext Context
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public IQueryable ExecuteWhere(string property, object value)
        {
            if (value is XPathAxisElement && property == "ID")
            {
                var predicate = ((XPathAxisElement)value).Predicates.First();

                queryWhereProperty = predicate.Left;
                queryWhereValue = predicate.Right;
            }
            else
            {
                queryWhereProperty = property;
                queryWhereValue = value;
            }

            return this.ChildElements.AsQueryable();
        }

        public void ExecuteWhere(System.Linq.Expressions.Expression expression)
        {
        }

        public void ExecuteWhere(XPathAxisElement element)
        {
        }

        public void ExecuteWhere(XPathAxisElement element, XPathAxisElement childrenElement)
        {
            var predicate = childrenElement.Predicates.First();

            queryWhereProperty = predicate.Left;
            queryWhereValue = predicate.Right;
        }

        public void ClearPredicates()
        {
            queryWhereProperty = null;
            queryWhereValue = null;
        }


        public DefinitionKind Kind
        {
            get { throw new NotImplementedException(); }
        }


        public bool HasChildren
        {
            get { throw new NotImplementedException(); }
        }


        public string DebugInfo
        {
            get { throw new NotImplementedException(); }
        }


        public float ChildOrdinal
        {
            get { throw new NotImplementedException(); }
        }


        public IRoot Root
        {
            get { throw new NotImplementedException(); }
        }


        public Modifiers Modifiers
        {
            get { throw new NotImplementedException(); }
        }


        public bool IsChildrenLoaded
        {
            get { throw new NotImplementedException(); }
        }


        public IAbstraXExtension LoadExtension(IBase baseObject)
        {
            throw new NotImplementedException();
        }

        public void AddView(Hydra.Shell.Interfaces.IDocumentView view)
        {
            throw new NotImplementedException();
        }

        public void CloseView(Hydra.Shell.Interfaces.IDocumentView view)
        {
            throw new NotImplementedException();
        }

        public void CloseAllViews()
        {
            throw new NotImplementedException();
        }

        public void UpdateAllViews()
        {
            throw new NotImplementedException();
        }
    }
}
